﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace _00_TCP_客户端
{
    public enum MessageType
    {
        /// <summary>
        /// 文本消息
        /// </summary>
        TextMessage = 0,
        /// <summary>
        /// 心跳消息
        /// </summary>
        Heartbeat = 1,
        /// <summary>
        /// 个人消息
        /// </summary>
        PersonalInformation,
        /// <summary>
        /// 获取服务器分配的IP地址与端口号
        /// </summary>
        IPAndPort

    }

    public partial class Frm_Client : Form
    {
        /// <summary>
        /// 创建Socket对象
        /// </summary>
        Socket socketClient = null;

        //定义变量记录服务器分配的IP地址与端口号
        string RemoteEndPoint = string.Empty;
        
        public Frm_Client()
        {
            InitializeComponent();
            //取消跨线程访问控件
            CheckForIllegalCrossThreadCalls = false;
        }
        /// <summary>
        /// 客户端-连接服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void button1_Click(object sender, EventArgs e)
        {
            //第一步:实例化Socket对象
            //AddressFamily.InterNetwork：IPV4协议
            //SocketType.Stream：流式套接字
            //ProtocolType.Tcp：TCP协议
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //第二步:创建绑定的IP地址与端口号
            IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(this.textBox2.Text));

            try
            {
                //链接服务器
                socketClient.Connect(iPEndPoint);
                //接收服务器发送过来的消息
                Task.Run(ReceiveMessage);
                //提示连接服务器成功
                richTextBox1.SelectionColor = Color.Black; //提示链接成功,向richTextBox1中添加内容，颜色为黑色
                richTextBox1.AppendText("连接服务器成功\r\n");
                //按钮取消使能，防止重复连接
                button1.Enabled = false;
            }
            catch (Exception ex)//异常错误
            {
                richTextBox1.SelectionColor = Color.Red; //提示链接成功,向richTextBox1中添加内容，颜色为黑色
                richTextBox1.AppendText("连接服务器失败，原因:" + ex.Message + "\r\n");
            }
            
        }

        public void ReceiveMessage()
        {
            while (true)
            {
                //创建Byte数组来接收内容
                byte[] buffer = new byte[1024 * 1024 * 2];
                try
                {
                    int Length = socketClient.Receive(buffer);//阻塞当前所在线程，如果接受到消息会自动解除阻塞
                    //判断是否有内容
                    if (Length > 0)
                    {
                        //获取第一个字节然后转换成枚举
                        MessageType messageType = (MessageType)buffer[0];
                        //判断消息类型
                        switch (messageType)
                        {
                            case MessageType.TextMessage:
                                //获取内容
                                string message = Encoding.Default.GetString(buffer, 1, Length - 1);
                                //提示接收到的消息
                                richTextBox1.SelectionColor = Color.Black;
                                richTextBox1.AppendText("接收到服务器消息:" + message + "\r\n");
                                break;
                            case MessageType.Heartbeat:
                                break;
                            case MessageType.IPAndPort:
                                //获取内容
                                string ipAndPort = Encoding.Default.GetString(buffer, 1, Length - 1);
                                //对变量进行赋值
                                RemoteEndPoint = ipAndPort;
                                //链接成功之后发送个人消息：将输入的内容转换为byte数组
                                byte[] bytes = Encoding.Default.GetBytes(RemoteEndPoint + "|" + this.textBox4.Text);
                                //创建新的数组比原有数组长度+1
                                byte[] newBytes = new byte[bytes.Length + 1];
                                //设置第一个字节为:MessageType.TextMessage
                                newBytes[0] = (byte)MessageType.PersonalInformation;
                                //将原有数组复制到新数组中,从第二个字节开始
                                bytes.CopyTo(newBytes, 1);
                                //发送消息
                                socketClient.Send(newBytes);
                                break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    richTextBox1.SelectionColor = Color.Red;
                    richTextBox1.AppendText("接收服务器消息失败，原因:" + ex.Message + "\r\n");
                    break;
                }
            }
        }
        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            socketClient.Close();
            richTextBox1.SelectionColor = Color.Black;
            richTextBox1.AppendText("断开连接成功\r\n");
            this.button1.Enabled = true;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //将输入的内容转换为byte数组
            byte[] bytes = Encoding.Default.GetBytes(textBox3.Text);
            //创建新的数组比原有数组长度+1
            byte[] newBytes = new byte[bytes.Length + 1];
            //设置第一个字节为:MessageType.TextMessage
            newBytes[0] = (byte)MessageType.TextMessage;
            //将原有数组复制到新数组中,从第二个字节开始
            bytes.CopyTo(newBytes, 1);
            //发送消息
            socketClient.Send(newBytes);
        }
    }
}
